package framework.helpers;

import java.util.List;
import java.util.Set;

import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.Keys;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.Select;

import framework.ApplicationManager;

public class BaseHelperWithWebDriver extends BaseHelper 
{
    private WebDriver driver;
    private Actions actions;
    
    public BaseHelperWithWebDriver(ApplicationManager app) {
        super(app);
        driver = app.getWebDriverHelper().getDriver();
        actions = new Actions(driver);
    }
    
	/**
	 * Возвращает найденный по локатору элемент
	 *
	 * @param by локатор элемента
	 * @return найденный элемент
	 */
	protected WebElement findElement(By by) {
    	log.trace(by);
    	WebElement element = driver.findElement(by);
        highlightElement(element);
		return element;
    }

	/**
	 * Возвращает список найденных по локатору элементов
	 *
	 * @param by локатор элемента
	 * @return список найденных элементов
	 */
    protected List<WebElement> findElements(By by) {
    	log.trace(by);
    	return driver.findElements(by);
    }

	/**
	 * Возвращает количество найденных по локатору элементов
	 *
	 * @param by локатор элемента
	 * @return количество найденных элементов
	 */
    protected int countElements(By by) {
    	log.debug(by);
    	return findElements(by).size();
    }

	/**
	 * Кликаем по найденному по локатору элементу
	 *
	 * @param by локатор элемента
	 */
    protected void click(By by) {
    	log.debug(by);
    	click(findElement(by));
    }   
 
	/**
	 * Кликаем по найденному по элементу
	 *
	 * @param element элемент
	 */
    protected void click(WebElement element) {
    	log.trace(element);
    	element.click();
    } 

 	/**
 	 * Вводим текст в элемент по локатору
 	 *
 	 * @param by локатор элемента
 	 * @param text вводимый текст
 	 */
    protected void type(By by, String text) {
    	log.debug(by + ", text = " + text);
    	WebElement element = findElement(by);
		element.clear();
        element.sendKeys(text);
    }    

 	/**
 	 * Выбираем элемент из комбобокса по тексту
 	 *
 	 * @param by локатор комбобокса
 	 * @param text текст искомого элемента
 	 */
    protected void selectByText(By by, String text) {
    	log.debug(by + ", text = " + text);
    	new Select(findElement(by)).selectByVisibleText(text);
    }
 
 	/**
 	 * Двойной клик по элементу
 	 *
  	 * @param element элемент
 	 */
	protected void dblClick(WebElement element) {
		log.debug(element);
		actions.doubleClick(element).build().perform();
	}    

 	/**
 	 * Проверяет наличие элемента по локатору
 	 *
  	 * @param by локатор элемента
 	 */
    protected boolean isElementPresent(By by) {
    	log.debug(by);
    	try {
            findElement(by);
            return true;
        } catch (NoSuchElementException e) {
            return false;
        }
    }   

 	/**
 	 * Открывает заданный url 
 	 *
  	 * @param url адрес страницы
 	 */
    protected void openUrl(String url) {
    	log.debug(url);
    	driver.get(url);
    }

 	/**
 	 * Возвращает url текущей страницы 
 	 *
  	 * @return url страницы
 	 */
    protected String getCurrentUrl() {
    	String currentUrl = driver.getCurrentUrl();
    	log.debug(currentUrl);
		return currentUrl;
	}      

 	/**
 	 * Проверка наличия текста в url текущей страницы 
 	 *
 	 * @param text текст для поиска в url
  	 * @return результат проверки
 	 */
    protected boolean isCurrentUrlContains(String text) {
    	log.debug(text);
    	return getCurrentUrl().contains(text);
    }
 
 	/**
 	 * Выполняет JavaScript для элемента 
 	 *
 	 * @param script исполняемый javascript
 	 * @param element элемент, на котором будет выполняеться javascript
  	 * @return результат выполнения javascriptа
 	 */
    protected Object executeJavaScript(String script, WebElement element) {
    	log.trace(script);
    	JavascriptExecutor js = (JavascriptExecutor) driver;
    	return js.executeScript(script, element);
    }
 
 	/**
 	 * Выполняет JavaScript 
 	 *
 	 * @param script исполняемый javascript
 	 * @return результат выполнения javascriptа
 	 */
    protected Object executeJavaScript(String script) {
    	return executeJavaScript(script, null);
    }    
    
    private void highlightElement(WebElement element) {
        String previousColor = getBackgroundColor(element);
        changeBackgroundColor(element, "red");
        sleep(1);
        changeBackgroundColor(element, previousColor);    	
    }

	private void changeBackgroundColor(WebElement element, String color) {
    	executeJavaScript("arguments[0].style.backgroundColor = '" + color + "'", element);	
    }
    
    private String getBackgroundColor(WebElement element) {
    	return element.getCssValue("backgroundColor");
    }
    
 	/**
 	 * Возвращает имя активного окна
 	 *
 	 * @return имя активного окна
 	 */
    protected String getWindowHandle() {
    	String windowHandle = driver.getWindowHandle();
    	log.debug(windowHandle);
    	return windowHandle;
    }

 	/**
 	 * Возвращает список активных окон
 	 *
 	 * @return список активных окон
 	 */
    protected Set<String> getWindowHandles() {
    	Set<String> windowHandles = driver.getWindowHandles();
    	log.debug(windowHandles);
    	return windowHandles;
    }

 	/**
 	 * Переключает драйвер на новое окно
 	 *
 	 * @param window имя окна
 	 */
    protected WebDriver switchToWindow(String window) {
    	log.debug("window = " + window);
    	return driver.switchTo().window(window);
    }
    
 	/**
 	 * Обновляет страницу
 	 */
    protected void refresh() {
    	log.debug("refresh window");
    	actions.keyDown(Keys.CONTROL).sendKeys(Keys.F5).keyUp(Keys.CONTROL).build().perform();
    }
 
	/**
 	 * Пролистывает страницу к элементу
 	 *
 	 * @param by локатор элемента
 	 */
    protected void moveToElement(By by) {
    	log.debug(by);
    	actions.moveToElement(findElement(by)).build().perform();
	}
 
 	/**
 	 * Открывает ссылку в новом окне и задает имя окна
 	 *
 	 * @param url ссылка для открытия
 	 * @param name имя окна
 	 * @return идентификатор окна
 	 */
    protected String openInNewWindow(String url, String name) {
    	((JavascriptExecutor) driver).executeScript("window.open(arguments[0],\"" + name + "\")", url);
    	return name;
    }
    
	/**
	 * Ожидание завершения ajax на странице
	 */
	protected void waitWhileAjaxCompleted() {
		for (int i = 0; i < app.getIntProperty("implicitWait"); i++) {
			if (isAjaxCompleted())
				return;
			sleep(app.getIntProperty("pauseForAjaxWaiting"));
		}
	}

	private boolean isAjaxCompleted() {
		return (Long) executeJavaScript("return window.jQuery.active") == 0;
	}    
}
